#include <scene.h>

#include <object.h>
#include <line.h>
#include <circle.h>
#include <polygon.h>

#include <visual.h>
#include <surface.h>

#include <unittest.h>

/**
 * DESC: Tests scene rendering using transparency
 * IMP: HIGH
 */

int main( int argc, char *argv[] )
{
  visual_init( 800, 600 );

  coord_t pos = { 0, 0 };
  surface_t *surface = surface_new( 800, 600 );
  assert_not_null( surface );

  scene_t *scene;

  uint16_t depth = 0;

  scene = scene_new();
  assert_not_null( scene );

  color_t color;

  line_t *line = line_new();
  COLOR_FROM_ARGB( color, COLOR_RED );
  object_init4( OBJECT( line ), color, 1.0, depth++ );
  SET_RECT( line->r, 0, 0, 800, 600 );
  scene_add_object( scene, OBJECT( line ) );

  circle_t *circle1 = circle_new();
  COLOR_FROM_ARGB( color, COLOR_RED );
  object_init4(circle1, color, 0.5, depth++ );
  SET_COORD( circle1->center, 300, 300 );
  circle1->radius = 100;
  scene_add_object( scene, OBJECT( circle1 ) );

  circle_t *circle2 = circle_new();
  COLOR_FROM_ARGB( color, COLOR_GREEN );
  object_init4( circle2, color, 0.5, depth++ );
  SET_COORD( circle2->center, 400, 300 );
  circle2->radius = 100;
  scene_add_object( scene, OBJECT( circle2 ) );

  circle_t *circle3 = circle_new();
  COLOR_FROM_ARGB( color, COLOR_BLUE );
  object_init4( circle3, color, 0.5, depth++ );
  SET_COORD( circle3->center, 500, 300 );
  circle3->radius = 100;
  scene_add_object( scene, OBJECT( circle3 ) );

  OBJECT_UNSET_DRAW_OPT( line, DRAW_FILL );
  OBJECT_UNSET_DRAW_OPT( circle1, DRAW_FILL );
  OBJECT_UNSET_DRAW_OPT( circle2, DRAW_FILL );
  OBJECT_UNSET_DRAW_OPT( circle3, DRAW_FILL );

  scene_render( scene, surface );

  visual_display( surface, pos );
  visual_update();
  visual_waitkey();
  surface_clear( surface );

  OBJECT_SET_DRAW_OPT( line, DRAW_FILL );
  OBJECT_SET_DRAW_OPT( circle1, DRAW_FILL );
  OBJECT_SET_DRAW_OPT( circle2, DRAW_FILL );
  OBJECT_SET_DRAW_OPT( circle3, DRAW_FILL );

  scene_render( scene, surface );

  visual_display( surface, pos );
  visual_update();
  visual_waitkey();
  surface_clear( surface );

  OBJECT_UNSET_DRAW_OPT( line, DRAW_FILL );
  OBJECT_UNSET_DRAW_OPT( circle1, DRAW_FILL );
  OBJECT_UNSET_DRAW_OPT( circle2, DRAW_FILL );
  OBJECT_UNSET_DRAW_OPT( circle3, DRAW_FILL );

  OBJECT_SET_DRAW_OPT( line, DRAW_ANTIALIAS );
  OBJECT_SET_DRAW_OPT( circle1, DRAW_ANTIALIAS );
  OBJECT_SET_DRAW_OPT( circle2, DRAW_ANTIALIAS );
  OBJECT_SET_DRAW_OPT( circle3, DRAW_ANTIALIAS );

  scene_render( scene, surface );

  visual_display( surface, pos );
  visual_update();
  visual_waitkey();
  surface_clear( surface );

  OBJECT_SET_DRAW_OPT( line, DRAW_FILL );
  OBJECT_SET_DRAW_OPT( circle1, DRAW_FILL );
  OBJECT_SET_DRAW_OPT( circle2, DRAW_FILL );
  OBJECT_SET_DRAW_OPT( circle3, DRAW_FILL );

  OBJECT_SET_DRAW_OPT( line, DRAW_ANTIALIAS );
  OBJECT_SET_DRAW_OPT( circle1, DRAW_ANTIALIAS );
  OBJECT_SET_DRAW_OPT( circle2, DRAW_ANTIALIAS );
  OBJECT_SET_DRAW_OPT( circle3, DRAW_ANTIALIAS );

  scene_render( scene, surface );

  visual_display( surface, pos );
  visual_update();
  visual_waitkey();
  surface_clear( surface );

  scene_free_objects( scene );

  polygon_t *polygon1 = polygon_new();
  COLOR_FROM_ARGB( color, COLOR_RED );
  object_init4( polygon1, color, 0.5, depth++ );
  polygon_add_vertex( polygon1, 100, 100 );
  polygon_add_vertex( polygon1, 700, 500 );
  polygon_add_vertex( polygon1, 100, 500 );
  polygon_add_vertex( polygon1, 700, 100 );
  scene_add_object( scene, OBJECT( polygon1 ) );

  polygon_t *polygon2 = polygon_new();
  COLOR_FROM_ARGB( color, COLOR_BLUE );
  object_init4( polygon2, color, 0.5, depth++ );
  polygon_add_vertex( polygon2, 200,  50 );
  polygon_add_vertex( polygon2, 600,  50 );
  polygon_add_vertex( polygon2, 600, 550 );
  polygon_add_vertex( polygon2, 200, 550 );
  scene_add_object( scene, OBJECT( polygon2 ) );

  scene_render( scene, surface );

  visual_display( surface, pos );
  visual_update();
  visual_waitkey();
  surface_clear( surface );


  surface_free( surface );

  scene_free_objects( scene );
  scene_free( scene );

  visual_quit();

  return 0;
}
